//ts的基本数据类型文件

/*
    格式：
    声明类型变量的格式  关键字可以let  const  var
    关键字 变量：数据类型 = 值

    关键字 变量：数据类型；
    数据类型 = 值

    关键字 变量 = 值

    ts的特点：
        1、在ts中，变量要声明数据类型，且数据类型声明之后，赋值只能是同一数据类型的数据，否则报错；
        2、当变量和赋值同时进行，将变量的数据类型声明，没写的时候，它赋予的第一个值的类型，就是该变量的数据类型。
    
    在ts中要进行类型声明，变量类型声明、形参类型声明、函数返回值类型声明
    当指定了类型声明之后，ts编辑器就会根据类型声明声明的类型去自动检查是否符合类型，符合 执行代码，不符合 报错
    当指定类型声明之后，该变量只能存储该类型的值

    ts拥有自动的类型判断机制
 */



//1、number
let num: number;
num = 123;
// num = '456';  报错
console.log(num)

let num1: number = 789;
console.log(num1)

//2、string
let str1: string = 'abc';
let str2: string = 'def';
let str3: string;
str3 = str1 + str2;//abcdef
str3 = str1 + num1;//abc789 拼串了
console.log(str3)

//3、boolean
let bool1: boolean;
bool1 = true;
bool1 = false;
// bool1 = 1 报错
console.log(bool1)

//使用一个关键字声明多个变量
let str4: string, bool4: boolean, num4: number;
str4 = 'str4';
bool4 = true;
num4 = 4;
console.log(str4, bool4, num4)
//当你声明完变量数据类型的时候，他就不能变化，如果赋的值不是声明的数据类型，就会报错。

//当变量和赋值同时进行，将变量的数据类型声明，没写的时候，它赋予的第一个值的类型，就是该变量的数据类型。
let bool5 = true;
console.log(bool5)

//4、字面量   字面量的特点 变量的数据类型和值一起给 ，但是还是要赋值，值必须和第一次一样，变了会报错
let a: 'test';
a = 'test';
// a = 'test1';  报错
console.log(a)

let b: true;
b = true;
// b = false; 报错
console.log(b)

//字面量的  联合类型  数据的类型可以是多个，值，必须是设置好的。
let bb: 'hello' | 'nihao' | true | 123;
bb = 'hello';
bb = 'nihao';
bb = true;
// bb = false; 报错
bb = 123;
console.log(bb)

//5、any 
//有时候 我们声明一个变量，我们不知道他是什么数据类型，但是ts中变量必须声明数据类型。
//any 数据类型的特点：1、它可以被赋值为任意数据类型；2、它还可以赋值给任意数据类型
let cc: any;
cc = 123;
cc = '123';
cc = true;//  any 可以被赋值为任意数据类型
console.log(cc)
let dd: string;
dd = cc;//  any  还 可以赋值给任意数据类型
console.log(dd)

//6、unknown
//特点：unknown 数据类型的变量，可以被赋值为任意数据类型，但是不能赋值给任意数据类型，只能赋值给unknown数据类型。
let ee: unknown;
ee = 789;
ee = '你好啊';//unknown 可以被赋值为任意数据类型
console.log(ee);
console.log(typeof(ee))
let ff: string;
// ff = ee;  报错   但是 unknown 不能赋值给任意数据类型,只能赋值给unknown数据类型。
let gg: unknown;
gg = ee;
console.log(gg)

//any 与 unknown 的区别： 都可以被赋值为任意数据类型，但是，any可以赋值给任意数据类型，但是unknown不能赋值给任意数据类型，只能赋值给unknown数据类型。
//any 不建议使用 能使用unknown就不要使用any。any容易出bug。

//7、void   
//void 表示两个值：不是undefined，就是null；
//通常用于：说明函数的返回值不能是undefined和null之外的值。


//在ts中，函数如何表示
/*
function 函数名(形参1：形参1的数据类型，形参2：形参2的数据类型)：函数返回值的数据类型{
    return  xxx
}
*/
function fun1(a: number, b: number): number {
    return a + b
}
console.log(fun1(1, 2));

function fun2(a: number, b: string): string {
    return a + b
}
console.log(fun2(521, "世界"))//拼串了

function fun3(a: string, b: number): void {
    let c: string = a + b
    console.log(c)
}
console.log(fun3('世界', 521))

/*
    ts的基本写法
    关键字  变量名 ： 变量数据类型声明  =  变量值

    关键字  变量名 ： 变量数据类型声明
    变量名 = 变量值

    关键字  变量名  =  变量值
*/

//8、object 对象
/*
    在js中 对象：
    let obj = {
        name:'tom',
        age:20
    }
*/

//(1)对象的 属性名和属性值的数据类型  是固定的，以及属性的个数也是固定的。  有一点不一样，就会报错
//当对象的数据类型规定完毕后，创建的对象必须要严格按照规定的数据类型进行创建，不能多也不能少，数据类型也不能不同。
let obj1:{name:string,age:number};
obj1 = {
    name:'tome',
    age:20,
    // sex:'男'  多了会报错，少了也会报错
}
console.log(obj1)

//(2) 规定属性的数据类型时，在属性名后面加?，表示该属性可有可无，写不写都不会报错，具有一定的灵活性。
//可以使对象中的某个，或者某些属性变得灵活，可有可无。
let obj2:{name:string,age:number,sex?:string,hobby?:string}
obj2 = {
    name:'json',
    age:18,
    // sex:'男'  该项写不写都不会报错
    hobby:'敲代码'//该项也是写不写都不会报错。
}

//(3)有没有可能属性名都不确定的
//[propName:string]:unknown 这一步操作，就是代表 属性名不确定，可以任意写，但是是字符串数据；属性值为unknown，可以是任意数据类型。  propName 是自定义的，可以任意改变，比如 attrbuteName
let obj3:{name:string,age:number,[propName:string]:unknown}
obj3 = {
    name:'juury',
    age:20,
    sex:'女',
    hobby:['打球','学习','看书']
}
console.log(obj3)

let obj4:{name:string,age:number,[attrbuteName:string]:unknown}
obj4 = {
    name:'jack',
    age:18,
    sex:'男'
}
console.log(obj4)

//9、array  数组

//(1) 数组中的所有元素，数据类型是 固定且一致的；
let arr1:string[];//代表数组arr1中的所有元素都是字符串类型，也只能是字符串类型
arr1 = ['tom','jack','juury'];
console.log(arr1)

let arr2:number[];//代表数组 arr2中的所有元素 都只能是number类型
arr2 = [20,18,25]
console.log(arr2)

let arr3:Array<number>;//代表变量arr3是数组，数组中的元素又都是number类型。
arr3 = [12,23,34]
console.log(arr3)

//10、元组
//现实中，有可能存在，数组中的元素，数据类型不是统一的，是多元的。
//元组：元组表示的是一个 长度和元素的数据类型已知的，各个元素数据类型可以不一致的  数组。
let arr4:[string,boolean,number];
arr4 = ['hello',true,2];
console.log(arr4)

//11、枚举
//枚举是对JavaScript标准数据类型的一个补充。
//使用枚举类型可以为一组数值赋予美好的名字。
//枚举可以理解为，一组数值存到了枚举对象中，并给这一组数值赋予了美好的名字。通过 枚举数据的名字[编号] 可以拿到存的值，也可以通过  枚举数据的名字["里面存的值"]  拿到值对应的编号
enum Color {
    Yellow,//0
    Pink,//1
    Blue//2
}
let monkey:Color ;
monkey = Color.Pink;
console.log(monkey);// 1

//通过 枚举数据的名字 . 里面存的值 或者 枚举数据的名字["里面存的值"] ，可以拿到 存的值在枚举中的编号  类似于数组的下标，默认是从0开始的。
console.log(Color.Yellow,Color['Pink'],Color.Blue);// 0 1 2
//通过 枚举数据的名字[编号]  可以拿到编号对应的值
console.log(Color[0],Color[1],Color[2]);// Yellow Pink Blue


//手动指定枚举的值
enum Color1{
    Yellow = 5,
    Pink,
    Blue
}
console.log(Color1[5]) //Yellow
console.log(Color1.Pink,Color1['Blue'])// 6  7
console.log(Color1[5],Color1[6],Color1[7])//Yellow Pink Blue

//类型联合
let aa:'男' | 1 | true;
aa = '男';
aa = 1;
aa = true;
// aa = false; 报错
console.log(aa)

//类型联合在函数中如何表示
function fun4(name:string,sex:'男' | 1 | true):void{
    console.log(name,sex)
}
fun4('tom','男')

//ts中的基本数据类型：number、string、boolean、void、字面量、类型联合、any、unknown、对象、数组、元组、枚举


//类型断言
//例如：一个函数中，他的参数x x的数据类型可能是数组，也可能是string  首先使用了类型联合,根据x参数，数据类型的不同，执行对应的代码。可用if...else...，type测出x的数据类型，从而执行不同代码。而 ts中有自己的判断方式。
function fun5(x:string | number ){
    /*
        类型断言的两种方式：
        1、 <数据类型> 值  
        2、值  as  类型   tsx文件当中只能使用这种方式
    */
    if((<string>x).length){
        console.log('string');
        return (<string>x).length
    }else{
        console.log('number');
        return x.toString().length
    }
}
console.log(fun5(123))

function fun6(y:string | boolean){
    //类型断言可以混合使用
    //类型断言：手动指定一个值的类型
    if((<string>y).length){
        console.log('string');
        return (y as string).length
    }else{
        console.log('boolean');
        return y.toString().length
    }
}
console.log(fun6(true))

//类型推断
/*
    ts中没有明确指定类型时，自动推断出一个数据类型
    一种：定义变量且赋值时，推断为对应的数据类型；
    二种：定义变量未赋值时，推断它的数据类型为any。
*/
let test1 = 1;
console.log(typeof(test1));//number
let test2 ;
test2 = true;
test2 = 123;
//都不报错 证明test2的数据类型刚开始为 any，随着赋值的数据类型变化而变化

//ts的基本数据类型：number、string、boolean、void、字面量、any、unknown、类型联合、对象、数组、元组、枚举、类型断言、类型推理。